#pragma once

#define WIN32_LEAN_AND_MEAN
#define DIRECTINPUT_VERSION 0x0800
#include <windows.h>
#include <dinput.h>
#include <vector>
#include <tchar.h>

namespace Diol
{

/*
	DeviceEnumerationTrigger

	Base class for the object that can be used to trigger a device enumeration (ie an update 
	of the Device List)at the DeviceManager level.
*/
class DeviceEnumerationTrigger
{
public:
	virtual~ DeviceEnumerationTrigger() {}
	virtual bool	enumerationNeeded() = 0;
};

/*
	WindowsHookEnumerationTrigger

	A trigger based on a Windows Proc hook. The hook is installed, then
	whenever a WM_DEVICECHANGE message is received, the trigger indicates 
	that a device enumeration at the DeviceManager level is needed
*/
class WindowsHookEnumerationTrigger : public DeviceEnumerationTrigger
{
public:
	WindowsHookEnumerationTrigger( bool createInvisibleWindow );	
	virtual ~WindowsHookEnumerationTrigger();
	virtual bool	enumerationNeeded();

private:
	bool			createInvisibleWindow();
	static LRESULT CALLBACK invisibleWindowWndProc( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam );
	static const TCHAR* invisibleWindowClassName;

	static LRESULT CALLBACK wndProcHook( int nCode, WPARAM wParam, LPARAM lParam );
	static std::vector<WindowsHookEnumerationTrigger*> mTriggerInstances;
	static HHOOK	mHookHandle;
	
	bool			mCreateInvisibleWindow;
	HWND			mInvisibleWindow;
	bool			mEnumerationNeeded;
};	
	
/*
	TimeBasedEnumerationTrigger
*/
class TimeBasedEnumerationTrigger : public DeviceEnumerationTrigger
{
public:
	TimeBasedEnumerationTrigger( unsigned int intervalInMs );	
	virtual bool	enumerationNeeded();

private:
	int				updateNextTime();

	unsigned int	mIntervalInMs;
	unsigned int	mStartTime;
	unsigned int	mNextTime;
};	

}